﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

namespace HDJ.Framework.Core
{
   public static class InputManager
    {
        private static List<InputSetData> inputSetDataList = new List<InputSetData>();

        private static Dictionary<string, InputSetData> allInputSetDataDic = new Dictionary<string,InputSetData>();

        private static bool isSendInputPressEvent = false;

        public static CallBack<string, ButtonPressState> OnInputSetButtonPressEvent;

        public static CallBack<InputKeyTypeData, ButtonPressState> OnInputPressEvent;

        public static  void Init(bool isSendInputPressEvent)
        {
            InputManager.isSendInputPressEvent = isSendInputPressEvent;
            if (isSendInputPressEvent)
            {
                MonoBehaviourRuntime.Instance.OnLateUpdate += OnLateUpdate;

               Array temp = Enum.GetValues(typeof(KeyCode));
                List<KeyCode> list = new List<KeyCode>();
                for (int i = 0; i < temp.Length; i++)
                {
                    KeyCode keyCode = (KeyCode)temp.GetValue(i);

                    list.Add(keyCode);
                }
                keyBoardCodeArr = list.ToArray();
            }

            SetAllInputSetData( InputSetDataManager.LoadDataFromFile());
        }
        private static KeyCode[] keyBoardCodeArr;
        private static void OnLateUpdate()
        {
            if (isSendInputPressEvent == false)
                return;

           
            for (int i = 0; i < inputSetDataList.Count; i++)
            {
                InputSetData data = inputSetDataList[i];
                if (!pressButtons.Contains(data.key))
                {
                    if (CheckPressButtonDown(data) > 0 )
                    {
                        if (OnInputSetButtonPressEvent != null)
                        {
                            OnInputSetButtonPressEvent(data.key, ButtonPressState.Down);
                        }
                    }
                    if ( CheckPressButton(data) > 0)
                    {
                        if (OnInputSetButtonPressEvent != null)
                        {
                            OnInputSetButtonPressEvent(data.key, ButtonPressState.Press);
                        }
                    }
                    if (CheckPressButtonUp(data) > 0)
                    {
                        if (OnInputSetButtonPressEvent != null)
                        {
                            OnInputSetButtonPressEvent(data.key, ButtonPressState.Up);
                        }
                    }
                }
            }

           

            for (int i = 0; i < keyBoardCodeArr.Length; i++)
            {
                KeyCode keyCode = keyBoardCodeArr[i];

                if (Input.GetKeyDown(keyCode))
                {
                    if (OnInputPressEvent != null)
                    {
                        InputKeyTypeData temp = new InputKeyTypeData();
                        temp.keyType = InputKeyType.KeyCode;
                        temp.keyboardCode = keyCode;
                        OnInputPressEvent(temp, ButtonPressState.Down);
                    }
                }
                if (Input.GetKey(keyCode))
                {
                    if (OnInputPressEvent != null)
                    {
                        InputKeyTypeData temp = new InputKeyTypeData();
                        temp.keyType = InputKeyType.KeyCode;
                        temp.keyboardCode = keyCode;
                        OnInputPressEvent(temp, ButtonPressState.Press);
                    }
                }
                if (Input.GetKeyUp(keyCode))
                {
                    if (OnInputPressEvent != null)
                    {
                        InputKeyTypeData temp = new InputKeyTypeData();
                        temp.keyType = InputKeyType.KeyCode;
                        temp.keyboardCode = keyCode;
                        OnInputPressEvent(temp, ButtonPressState.Up);
                    }
                }
            }

        }
        public static void SetAllInputSetData(Dictionary<string, InputSetData> allInputSetDataDic)
        {
            InputManager.allInputSetDataDic = allInputSetDataDic;
            inputSetDataList = new List<InputSetData>(allInputSetDataDic.Values);
        }
        public static Dictionary<string, InputSetData> GetAllInputSetData()
        {
            return allInputSetDataDic;
        }

       private static  List<string> pressButtons = new List<string>();



        /// <summary>
        /// 获取按下或按住按钮的key
        /// </summary>
        /// <returns></returns>
        public static string[] GetPressButtons()
        {
            pressButtons.Clear();

            for (int i = 0; i < inputSetDataList.Count; i++)
            {
                InputSetData data = inputSetDataList[i];
                if (!pressButtons.Contains(data.key))
                {
                    if (CheckPressButtonDown(data)>0|| CheckPressButton(data)>0)
                    {
                        pressButtons.Add(data.key);
                    }
                }
            }

            return pressButtons.ToArray();
        }

        private static float CheckPressButtonDown(InputSetData key)
        {
            float res = 0;
            float temp = 0;
            for (int i = 0; i < key.InputKeyTypeDataList.Count; i++)
            {
                InputKeyTypeData data = key.InputKeyTypeDataList[i];
                if (data.keyType == InputKeyType.KeyCode)
                {
                    if (Input.GetKeyDown(data.keyboardCode))
                    {
                        temp = 1f;
                    }
                }

                else if (data.keyType == InputKeyType.Custom)
                {
                    if (data.customButtonCheck != null)
                    {
                        if (data.customButtonCheck.pressButtonDown != null && data.customButtonCheck.pressButtonDown() > 0)
                        {
                            float num = data.customButtonCheck.pressButtonDown();
                            num = Mathf.Clamp01(num);
                            if (temp < num)
                            {
                                temp = num;
                            }
                        }
                    }
                }
            }
            res = temp;
            return res;
        }
        private static float CheckPressButtonUp(InputSetData key)
        {
            float res = 0;
            float temp = 0;
            for (int i = 0; i < key.InputKeyTypeDataList.Count; i++)
            {
                InputKeyTypeData data = key.InputKeyTypeDataList[i];
                if (data.keyType == InputKeyType.KeyCode)
                {
                    if (Input.GetKeyUp(data.keyboardCode))
                    {

                        temp = 1f;
                    }
                }

                else if (data.keyType == InputKeyType.Custom)
                {
                    if (data.customButtonCheck != null)
                    {
                        if (data.customButtonCheck.pressButtonUp != null && data.customButtonCheck.pressButtonUp() > 0)
                        {
                            float num = data.customButtonCheck.pressButtonUp();
                            num = Mathf.Clamp01(num);
                            if (temp < num)
                            {
                                temp = num;
                            }
                        }
                    }
                }
            }
            res = temp;
            return res;
        }
        private static float CheckPressButton(InputSetData key)
        {
            float res = 0;
            float temp = 0;
            for (int i = 0; i < key.InputKeyTypeDataList.Count; i++)
            {
                InputKeyTypeData data = key.InputKeyTypeDataList[i];
                if (data.keyType == InputKeyType.KeyCode)
                {
                    if (Input.GetKey(data.keyboardCode))
                    {

                        temp = 1f;
                    }
                }
                else if (data.keyType == InputKeyType.Custom)
                {
                    if (data.customButtonCheck != null)
                    {
                        if (data.customButtonCheck.pressButton != null && data.customButtonCheck.pressButton() > 0)
                        {
                            float num = data.customButtonCheck.pressButton();
                            num = Mathf.Clamp01(num);
                            if (temp < num)
                            {
                                temp = num;
                            }
                        }
                    }
                }
            }
            res = temp;
            return res;
        }

        public static void AddInputSetData(List<InputSetData> data)
        {
            if (data != null)
            {
                for (int i = 0; i < data.Count; i++)
                {
                    AddInputSetData(data[i]);
                }
            }
        }
        public static void AddInputSetData(InputSetData data)
        {
            if (data != null)
            {
                
                if (allInputSetDataDic.ContainsKey(data.key))
                {
                   allInputSetDataDic[data.key] = data;

                }
                else
                {
                    inputSetDataList.Add(data);
                    allInputSetDataDic.Add(data.key, data);
                }
            }
        }
        public static float GetButtonDown(string key)
        {
            return GetButtonPress(key,  ButtonPressState.Down);
        }
        public static float GetButton(string key)
        {
            return GetButtonPress(key,  ButtonPressState.Press);
        }
        public static float GetButtonUp(string key)
        {
            return GetButtonPress(key,  ButtonPressState.Up);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="state">按钮状态，0按下, 1 按住,2 放开</param>
        /// <returns></returns>
        public static float GetButtonPress(string key, ButtonPressState state)
        {
            float res = -1;
            if (allInputSetDataDic.ContainsKey(key))
            {
                InputSetData setData = allInputSetDataDic[key];
                switch (state)
                {
                    case  ButtonPressState.Down:
                        return CheckPressButtonDown(setData);
                    case  ButtonPressState.Press:
                        return CheckPressButton(setData);
                    case  ButtonPressState.Up:
                        return CheckPressButtonUp(setData);
                }

            }
            return res;
        }

        /// <summary>
        /// 某个按键是否已经被设置
        /// </summary>
        /// <param name="keyButton"></param>
        /// <returns></returns>
        public static bool IsAlreadySetKeyButton(InputKeyTypeData keyButton)
        {
            for (int i = 0; i < inputSetDataList.Count; i++)
            {
                InputSetData data = inputSetDataList[i];
                for (int j = 0; j < data.InputKeyTypeDataList.Count; j++)
                {
                    InputKeyTypeData temp = data.InputKeyTypeDataList[j];

                    if (keyButton.Equals(temp))
                        return true;
                }
            }
            return false;
        }
    }

    public class InputSetData
    {
        public string key="";
        /// <summary>
        /// 名字
        /// </summary>
        public string name="";

        public List<InputKeyTypeData> InputKeyTypeDataList = new List<InputKeyTypeData>();

    }
    public class InputKeyTypeData
    {
        /// <summary>
        /// 按键类型
        /// </summary>
        public InputKeyType keyType;
        /// <summary>
        /// 鼠标键盘按键 keyType==InputKeyType.Keyboard时使用
        /// </summary>
        public KeyCode keyboardCode;

        /// <summary>
        /// 自定义按键 keyType==InputKeyType.Custom 时使用,返回0.0—1.0;
        /// </summary>
        public InputCustomButtonFunction customButtonCheck;

        public override bool Equals(object obj)
        {
            InputKeyTypeData temp = (InputKeyTypeData)obj;
            if (temp == null) return false;
            if(temp.keyType == keyType)
            {
                switch (keyType)
                {
                    case InputKeyType.KeyCode:
                        if (keyboardCode == temp.keyboardCode)
                            return true;
                        break;
                    case InputKeyType.Custom:
                        if (customButtonCheck == temp.customButtonCheck)
                            return true;
                        break;
                        
                }
            }
            return false;
        }

        public override string ToString()
        {
            string ss = "InputKeyType :" + keyType;
            if(keyType== InputKeyType.KeyCode)
            {
                ss += "  key :" + keyboardCode;
            }
  
            return ss;
        }
    }
    public class InputCustomButtonFunction
    {
        /// <summary>
        /// 自定义按键 keyType==InputKeyType.Custom 时使用,返回0.0—1.0;
        /// </summary>
        public CallBackR<float> pressButtonDown;
        public CallBackR<float> pressButton;
        public CallBackR<float> pressButtonUp;
    }
    /// <summary>
    /// 按键类型
    /// </summary>
    public enum InputKeyType
    {
        KeyCode,
        /// <summary>
        /// 自定义，如触屏UI按钮
        /// </summary>
        Custom,
    }

    public enum ButtonPressState
    {
        Down,
        Press,
        Up,
    }

}
